package org.liveboardgames.agricola.business;

import java.util.Set;

import org.liveboardgames.agricola.business.helper.GameHelper;
import org.liveboardgames.agricola.business.helper.SpecialPointsComputer;
import org.liveboardgames.agricola.domain.card.Card;
import org.liveboardgames.agricola.domain.common.SpecialPoint;
import org.liveboardgames.agricola.domain.player.Player;
import org.liveboardgames.agricola.domain.player.Score;

public class ScoreServiceImpl implements IScoreService {

  private GameHelper gameHelper;

  public ScoreServiceImpl() {
    gameHelper = new GameHelper();
  }

  public Score computeScore(Player player) {
    Score score = new Score();

    score.setFields(computeFields(player));
    score.setPastures(computePastures(player));
    score.setGrains(computeGrains(player));
    score.setVegetables(computeVegetables(player));
    score.setSheep(computeSheep(player));
    score.setBoar(computeBoar(player));
    score.setCattle(computeCattle(player));
    score.setFreeSpace(computeFreeSpace(player));
    score.setFencedStable(computeFencedStable(player));
    score.setClayHouse(computeClayHouse(player));
    score.setStoneHouse(computeStoneHouse(player));
    score.setFamilyMember(computeFamilyMember(player));
    score.setCards(computeCards(player));
    score.setSpecialPoints(computeSpecialPoints(player));

    return score;
  }

  private int computeSpecialPoints(Player player) {
    int points = 0;
    Set<Card> playedCards = player.getFarm().getPlayedCards();
    SpecialPointsComputer specialPointsComputer = new SpecialPointsComputer();
    for (Card card : playedCards) {
      Set<SpecialPoint> specialPoints = card.getSpecialPoints();
      for (SpecialPoint specialPoint : specialPoints) {
        points += specialPointsComputer.computeSpecialPoints(player, specialPoint);
      }
    }
    return points;
  }

  private int computeCards(Player player) {
    int points = 0;
    Set<Card> playedCards = player.getFarm().getPlayedCards();
    for (Card card : playedCards) {
      points += card.getPoints();
    }
    return points;
  }

  private int computeFamilyMember(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfFamilyMembers(player);
    points = 3 * numberOfElements;
    return points;
  }

  private int computeStoneHouse(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfStoneRooms(player.getFarm());
    points = 2 * numberOfElements;
    return points;
  }

  private int computeClayHouse(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfClayRooms(player.getFarm());
    points = numberOfElements;
    return points;
  }

  private int computeFencedStable(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfFencedStables(player.getFarm());
    points = numberOfElements;
    return points;
  }

  private int computeFreeSpace(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfFreeSpaces(player.getFarm());
    points = -numberOfElements;
    return points;
  }

  private int computeCattle(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfCattle(player.getFarm());
    switch (numberOfElements) {
      case 0:
        points = -1;
        break;
      case 1:
        points = 1;
        break;
      case 2:
      case 3:
        points = 2;
        break;
      case 4:
      case 5:
        points = 3;
        break;
      default:
        points = 4;
        break;
    }
    return points;
  }

  private int computeBoar(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfBoar(player.getFarm());
    switch (numberOfElements) {
      case 0:
        points = -1;
        break;
      case 1:
      case 2:
        points = 1;
        break;
      case 3:
      case 4:
        points = 2;
        break;
      case 5:
      case 6:
        points = 3;
        break;
      default:
        points = 4;
        break;
    }
    return points;
  }

  private int computeSheep(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfSheep(player.getFarm());
    switch (numberOfElements) {
      case 0:
        points = -1;
        break;
      case 1:
      case 2:
      case 3:
        points = 1;
        break;
      case 4:
      case 5:
        points = 2;
        break;
      case 6:
      case 7:
        points = 3;
        break;
      default:
        points = 4;
        break;
    }
    return points;
  }

  private int computeVegetables(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfVegetables(player.getFarm());
    switch (numberOfElements) {
      case 0:
        points = -1;
        break;
      case 1:
        points = 1;
        break;
      case 2:
        points = 2;
        break;
      case 3:
        points = 3;
        break;
      default:
        points = 4;
        break;
    }
    return points;
  }

  private int computeGrains(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfGrains(player.getFarm());
    switch (numberOfElements) {
      case 0:
        points = -1;
        break;
      case 1:
      case 2:
      case 3:
        points = 1;
        break;
      case 4:
      case 5:
        points = 2;
        break;
      case 6:
      case 7:
        points = 3;
        break;
      default:
        points = 4;
        break;
    }
    return points;
  }

  private int computePastures(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfPastures(player.getFarm());
    switch (numberOfElements) {
      case 0:
        points = -1;
        break;
      case 1:
        points = 1;
        break;
      case 2:
        points = 2;
        break;
      case 3:
        points = 3;
        break;
      default:
        points = 4;
        break;
    }
    return points;
  }

  private int computeFields(Player player) {
    int points = 0;
    int numberOfElements = gameHelper.getNumberOfFields(player.getFarm());
    switch (numberOfElements) {
      case 0:
      case 1:
        points = -1;
        break;
      case 2:
        points = 1;
        break;
      case 3:
        points = 2;
        break;
      case 4:
        points = 3;
        break;
      default:
        points = 4;
        break;
    }
    return points;
  }

}
